// -*- coding: utf-8 -*-
/*
author: zengbin93
email: zeng_bin8888@163.com
create_dt: 2022/12/16 19:37
describe: 价格分析相关功能
*/

use crate::svc::base::{DataFrame, StyleConfig};
use serde_json::Value;
use std::collections::HashMap;

/// 显示价格敏感性分析
pub fn show_price_sensitive(df: &DataFrame, config: Option<&StyleConfig>) -> DataFrame {
    let config = config.unwrap_or(&StyleConfig::default());
    
    let mut result = DataFrame::new();
    result.add_column("价格变化", crate::svc::base::DataType::Number, false);
    result.add_column("收益变化", crate::svc::base::DataType::Number, true);
    result.add_column("敏感性", crate::svc::base::DataType::Number, true);
    result.add_column("弹性", crate::svc::base::DataType::Number, true);
    
    result
}

/// 计算价格敏感性
pub fn calculate_price_sensitivity(prices: &[f64], returns: &[f64]) -> f64 {
    if prices.len() != returns.len() || prices.len() < 2 {
        return 0.0;
    }
    
    let mut price_changes = Vec::new();
    let mut return_changes = Vec::new();
    
    for i in 1..prices.len() {
        let price_change = (prices[i] - prices[i - 1]) / prices[i - 1];
        price_changes.push(price_change);
        return_changes.push(returns[i]);
    }
    
    // 计算价格变化和收益变化的相关性
    calculate_correlation(&price_changes, &return_changes)
}

/// 计算价格弹性
pub fn calculate_price_elasticity(prices: &[f64], volumes: &[f64]) -> f64 {
    if prices.len() != volumes.len() || prices.len() < 2 {
        return 0.0;
    }
    
    let mut price_changes = Vec::new();
    let mut volume_changes = Vec::new();
    
    for i in 1..prices.len() {
        let price_change = (prices[i] - prices[i - 1]) / prices[i - 1];
        let volume_change = (volumes[i] - volumes[i - 1]) / volumes[i - 1];
        
        if volume_change != 0.0 {
            price_changes.push(price_change);
            volume_changes.push(volume_change);
        }
    }
    
    if price_changes.is_empty() {
        return 0.0;
    }
    
    // 计算价格变化和成交量变化的相关性
    calculate_correlation(&price_changes, &volume_changes)
}

/// 计算价格动量
pub fn calculate_price_momentum(prices: &[f64], window: usize) -> Vec<f64> {
    if prices.len() < window {
        return vec![];
    }
    
    let mut momentum = Vec::new();
    
    for i in window..prices.len() {
        let current_price = prices[i];
        let past_price = prices[i - window];
        let momentum_value = (current_price - past_price) / past_price;
        momentum.push(momentum_value);
    }
    
    momentum
}

/// 计算价格波动率
pub fn calculate_price_volatility(prices: &[f64], window: usize) -> Vec<f64> {
    if prices.len() < window {
        return vec![];
    }
    
    let mut volatility = Vec::new();
    
    for i in window..prices.len() {
        let window_prices = &prices[(i - window)..i];
        let returns: Vec<f64> = window_prices.windows(2)
            .map(|w| (w[1] - w[0]) / w[0])
            .collect();
        
        let mean_return = returns.iter().sum::<f64>() / returns.len() as f64;
        let variance = returns.iter()
            .map(|r| (r - mean_return).powi(2))
            .sum::<f64>() / returns.len() as f64;
        
        volatility.push(variance.sqrt());
    }
    
    volatility
}

/// 计算价格支撑阻力位
pub fn calculate_support_resistance(prices: &[f64], window: usize) -> (Vec<f64>, Vec<f64>) {
    if prices.len() < window {
        return (vec![], vec![]);
    }
    
    let mut support_levels = Vec::new();
    let mut resistance_levels = Vec::new();
    
    for i in window..prices.len() {
        let window_prices = &prices[(i - window)..i];
        let current_price = prices[i];
        
        let min_price = window_prices.iter().fold(f64::INFINITY, |a, &b| a.min(b));
        let max_price = window_prices.iter().fold(f64::NEG_INFINITY, |a, &b| a.max(b));
        
        // 支撑位：当前价格接近窗口内最低价
        if current_price <= min_price * 1.02 {
            support_levels.push(min_price);
        } else {
            support_levels.push(0.0);
        }
        
        // 阻力位：当前价格接近窗口内最高价
        if current_price >= max_price * 0.98 {
            resistance_levels.push(max_price);
        } else {
            resistance_levels.push(0.0);
        }
    }
    
    (support_levels, resistance_levels)
}

/// 计算价格趋势强度
pub fn calculate_trend_strength(prices: &[f64], window: usize) -> Vec<f64> {
    if prices.len() < window {
        return vec![];
    }
    
    let mut trend_strength = Vec::new();
    
    for i in window..prices.len() {
        let window_prices = &prices[(i - window)..i];
        let current_price = prices[i];
        
        // 计算线性回归斜率
        let n = window_prices.len() as f64;
        let x_sum: f64 = (0..window_prices.len()).map(|x| x as f64).sum();
        let y_sum: f64 = window_prices.iter().sum();
        let xy_sum: f64 = window_prices.iter().enumerate()
            .map(|(i, &y)| i as f64 * y)
            .sum();
        let x2_sum: f64 = (0..window_prices.len()).map(|x| (x as f64).powi(2)).sum();
        
        let slope = if n * x2_sum - x_sum * x_sum != 0.0 {
            (n * xy_sum - x_sum * y_sum) / (n * x2_sum - x_sum * x_sum)
        } else {
            0.0
        };
        
        // 趋势强度：斜率与当前价格的比值
        let strength = if current_price > 0.0 {
            slope / current_price
        } else {
            0.0
        };
        
        trend_strength.push(strength);
    }
    
    trend_strength
}

/// 计算价格突破信号
pub fn calculate_breakout_signals(prices: &[f64], window: usize, threshold: f64) -> Vec<i32> {
    if prices.len() < window {
        return vec![];
    }
    
    let mut signals = Vec::new();
    
    for i in window..prices.len() {
        let window_prices = &prices[(i - window)..i];
        let current_price = prices[i];
        
        let max_price = window_prices.iter().fold(f64::NEG_INFINITY, |a, &b| a.max(b));
        let min_price = window_prices.iter().fold(f64::INFINITY, |a, &b| a.min(b));
        
        let upper_breakout = current_price > max_price * (1.0 + threshold);
        let lower_breakout = current_price < min_price * (1.0 - threshold);
        
        if upper_breakout {
            signals.push(1); // 向上突破
        } else if lower_breakout {
            signals.push(-1); // 向下突破
        } else {
            signals.push(0); // 无突破
        }
    }
    
    signals
}

/// 计算价格相关性
fn calculate_correlation(x: &[f64], y: &[f64]) -> f64 {
    if x.len() != y.len() || x.is_empty() {
        return 0.0;
    }
    
    let n = x.len() as f64;
    let sum_x: f64 = x.iter().sum();
    let sum_y: f64 = y.iter().sum();
    let sum_xy: f64 = x.iter().zip(y.iter()).map(|(a, b)| a * b).sum();
    let sum_x2: f64 = x.iter().map(|a| a * a).sum();
    let sum_y2: f64 = y.iter().map(|b| b * b).sum();
    
    let numerator = n * sum_xy - sum_x * sum_y;
    let denominator = ((n * sum_x2 - sum_x * sum_x) * (n * sum_y2 - sum_y * sum_y)).sqrt();
    
    if denominator > 0.0 {
        numerator / denominator
    } else {
        0.0
    }
}

/// 计算价格分布统计
pub fn calculate_price_distribution_stats(prices: &[f64]) -> HashMap<String, f64> {
    let mut stats = HashMap::new();
    
    if prices.is_empty() {
        return stats;
    }
    
    let n = prices.len() as f64;
    let sum: f64 = prices.iter().sum();
    let mean = sum / n;
    
    let variance = prices.iter()
        .map(|x| (x - mean).powi(2))
        .sum::<f64>() / n;
    let std_dev = variance.sqrt();
    
    let mut sorted_prices = prices.to_vec();
    sorted_prices.sort_by(|a, b| a.partial_cmp(b).unwrap());
    
    let min = sorted_prices[0];
    let max = sorted_prices[sorted_prices.len() - 1];
    let median = if n as usize % 2 == 0 {
        (sorted_prices[n as usize / 2 - 1] + sorted_prices[n as usize / 2]) / 2.0
    } else {
        sorted_prices[n as usize / 2]
    };
    
    let q1_index = (n * 0.25) as usize;
    let q3_index = (n * 0.75) as usize;
    let q1 = sorted_prices[q1_index];
    let q3 = sorted_prices[q3_index];
    
    // 计算偏度
    let skewness = prices.iter()
        .map(|x| ((x - mean) / std_dev).powi(3))
        .sum::<f64>() / n;
    
    // 计算峰度
    let kurtosis = prices.iter()
        .map(|x| ((x - mean) / std_dev).powi(4))
        .sum::<f64>() / n - 3.0;
    
    stats.insert("最小值".to_string(), min);
    stats.insert("最大值".to_string(), max);
    stats.insert("均值".to_string(), mean);
    stats.insert("中位数".to_string(), median);
    stats.insert("标准差".to_string(), std_dev);
    stats.insert("25%分位数".to_string(), q1);
    stats.insert("75%分位数".to_string(), q3);
    stats.insert("偏度".to_string(), skewness);
    stats.insert("峰度".to_string(), kurtosis);
    
    stats
} 